home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / sound / randysnd.zip / RANDYSND.CPP < prev    next >
C/C++ Source or Header  |  1992-06-12  |  16KB  |  631 lines

  1. /* randysnd.cpp */
  2.  
  3. // RandySnd is (C) 1992 Anthony McCarthy
  4. //
  5. // Feel free to use and abuse this program to your own ends.
  6. // However, it is provided FREE, AS-IS and with absolutely NO
  7. // WARRANTY whatsoever. Use it at your own risk.
  8. //
  9. // The above statement is especially appropriate as this is
  10. // my very first program built using MSC++ 7 and Microsoft's
  11. // Foundation Classes. As yet I haven't really got my head
  12. // around how to play with precompiled headers. Also, I ain't
  13. // yet played with the diagnostic services provided by MFC
  14. // and so there may well be memory leaks that I haven't seen
  15. // yet.
  16. //
  17. // Please forgive the proliferation of literal integers and
  18. // strings in the code - this code was a quick hack - they
  19. // should all really be symbolic at least.  Also, I haven't yet
  20. // developed/decided on a personal coding style for C++ so 
  21. // things might feel inconsistent.
  22. //
  23. // If you really like this program, a donation of a few pounds,
  24. // dollars, roubles, francs or whatever would be appreciated, to:
  25. // Anthony McCarthy, 14 Beryl Road, Bedminster, Bristol, BS3 3DH, UK
  26. //
  27. // Having said there's no warranty, please report any bugs, enhancement
  28. // requests or source code criticisms to:
  29. //   100012.3712@compuserve.com   
  30. //   amccarthy@cix.compulink.co.uk
  31. //   amc@beryl.demon.co.uk
  32.  
  33.  
  34. // CAVEAT: if you're trying to recompile this source with the same 
  35. // release of MSC 7.0 as I'm using, the compile will fail. Microsoft 
  36. // failed to include the AfxSig_vh enum in afxmsg.h although it is 
  37. // referenced in the ON_WM_DROPFILES() macro in the same file!  To work 
  38. // around this, I simply changed 'AfxSig_vh' to 'AfxSig_vw' in a copy 
  39. // of afxmsg.h.
  40.  
  41.  
  42. // Change History
  43. // ~~~~~~~~~~~~~~
  44. //
  45. // v1.00 : AMcC : 10June92 : initial creation
  46.  
  47.  
  48.  
  49. # include <afxwin.h>
  50. # include <afxcoll.h>
  51. # include <mmsystem.h>
  52. # include <commdlg.h>
  53. # include <shellapi.h>
  54. # include <stdlib.h>
  55. # include "randysnd.h"
  56.  
  57.  
  58.  
  59. static char scratchBuffer[512];
  60.  
  61.  
  62.  
  63. /*--------------------------------------------------------------------------*/
  64. /*                                                                          */
  65. /*                          C M a i n W i n d o w                           */
  66. /*                                                                          */
  67. /*--------------------------------------------------------------------------*/
  68.  
  69. class CMainDialog : public CModalDialog
  70. {
  71.  private:
  72.  
  73.  
  74.    CPtrList soundsList;
  75.  
  76.    BOOL bFilesChanged,
  77.         bAutoRandomiseChanged;
  78.  
  79.    CString curSysSound;
  80.  
  81.    WORD templateId;
  82.  
  83.  public:
  84.    static const char * iniFileName;
  85.  
  86.    CMainDialog(WORD dlgId) : CModalDialog(dlgId) { bFilesChanged = FALSE; 
  87.                                                    bAutoRandomiseChanged = FALSE;
  88.                                                    templateId = dlgId;
  89.                                                  }
  90.    ~CMainDialog();
  91.  
  92.    BOOL OnInitDialog();
  93.  
  94.    BOOL GetIniString(CString section, CString key, CString& value);
  95.    BOOL LoadWavFilesList(const CString & sysSound);
  96.    BOOL SaveWavFilesList(const CString & sysSound);
  97.    BOOL FlushWavFilesList();
  98.    BOOL GetSysSound(CString& sysSound);
  99.    BOOL TryToRandomizeSysSound(CString sysSound);
  100.  
  101.    afx_msg void OnAbout();
  102.    afx_msg void OnDestroy();
  103.    afx_msg void OnSysSndSelChange();
  104.  
  105.    afx_msg void OnFileSelChange();
  106.    afx_msg void OnPlaySound();
  107.    afx_msg void OnAddSoundFile();
  108.    afx_msg void OnRemoveSoundFile();
  109.    afx_msg void OnAutoRandomise();
  110.    afx_msg void OnRandomiseNow();
  111.    afx_msg void OnDropFiles(HDROP hDrop);
  112.  
  113.    DECLARE_MESSAGE_MAP()
  114.  
  115. };
  116.  
  117.  
  118. /*--------------------------------------------------------------------------*/
  119. /*                                                                          */
  120. /*                               C M y A p p                                */
  121. /*                                                                          */
  122. /*--------------------------------------------------------------------------*/
  123.  
  124. class CMyApp : public CWinApp
  125. {
  126.  public:
  127.     int  Run();
  128.     BOOL WantedMinimize();
  129. };
  130.  
  131.  
  132. BOOL CMyApp::WantedMinimize()
  133. {
  134.  return (    m_nCmdShow == SW_SHOWMINIMIZED
  135.           || m_nCmdShow == SW_MINIMIZE
  136.           || m_nCmdShow == SW_SHOWMINNOACTIVE );
  137. }
  138.  
  139.  
  140. int CMyApp::Run()
  141. {
  142.  WORD dlgId;
  143.  
  144.  if (WantedMinimize())
  145.     dlgId = IDD_WORKINPROGRESS;
  146.  else
  147.     dlgId = IDD_MAIN;
  148.  
  149.  CMainDialog mainDialog(dlgId);
  150.  
  151.  mainDialog.DoModal();
  152.  
  153.  return 0;
  154. }
  155.  
  156.  
  157.  
  158. // Static application object... the constructor for
  159. // this kicks everything off. 
  160. //
  161. // This comment is here because even though I find the 
  162. // concept of static intializers simple enough to comprehend,
  163. // its still damned difficult to see where the app 'gets going'.
  164.  
  165. CMyApp myApp;
  166.  
  167.  
  168.  
  169.  
  170. const char * CMainDialog::iniFileName = "randysnd.ini";
  171.  
  172. BEGIN_MESSAGE_MAP( CMainDialog, CModalDialog )
  173.     ON_COMMAND( ID_ABOUT          , OnAbout           )
  174.     ON_COMMAND( ID_PLAYSOUNDFILE  , OnPlaySound       )
  175.     ON_COMMAND( ID_ADDSOUNDFILE   , OnAddSoundFile    )
  176.     ON_COMMAND( ID_REMOVESOUNDFILE, OnRemoveSoundFile )
  177.     ON_COMMAND( ID_AUTORANDOMISE  , OnAutoRandomise   )
  178.     ON_COMMAND( ID_RANDOMIZENOW   , OnRandomiseNow    )
  179.  
  180.     ON_WM_DESTROY( )
  181.     ON_WM_DROPFILES( ) // *SIGH* MS omitted the AfxSig_vh enum from afxmsg.h!
  182.                        // To work round this, I modified the ON_WM_DROPFILES()
  183.                        // macro (in afxmsg.h) to use the AfxSig_vw signature.
  184.  
  185.     ON_CBN_SELCHANGE( ID_SYSTEMSOUNDS, OnSysSndSelChange )
  186.     ON_LBN_SELCHANGE( ID_FILESLIST   , OnFileSelChange )
  187. END_MESSAGE_MAP()
  188.  
  189.  
  190. CMainDialog::~CMainDialog()
  191. {
  192.  CString * pCstr;
  193.  
  194.  while (     ! soundsList.IsEmpty() 
  195.          &&  (pCstr = (CString *)soundsList.RemoveHead()) != NULL)
  196.        delete pCstr;
  197. }
  198.  
  199.  
  200. BOOL CMainDialog::GetSysSound(CString& sysSound)
  201. {
  202.  BOOL ok = FALSE;
  203.  CComboBox * cb = (CComboBox *)GetDlgItem(ID_SYSTEMSOUNDS);
  204.  CString * s = (CString *)(soundsList.GetAt(soundsList.FindIndex(cb->GetCurSel())));
  205.  
  206.  
  207.  if (! soundsList.IsEmpty())
  208.     {
  209.      sysSound = *s;
  210.      ok = TRUE;
  211.     }
  212.  
  213.  return ok;
  214. }
  215.  
  216.  
  217. BOOL CMainDialog::GetIniString(CString section, CString key, CString& value)
  218. {
  219.  BOOL ok;
  220.  
  221.  ok = GetPrivateProfileString( section, 
  222.                                key, 
  223.                                "", 
  224.                                value.GetBuffer(256), 
  225.                                256, 
  226.                                iniFileName ) > 0;
  227.  
  228.  value.ReleaseBuffer();
  229.  
  230.  return ok;
  231. }
  232.  
  233.  
  234. BOOL CMainDialog::FlushWavFilesList()
  235. {
  236.  BOOL ok = TRUE;
  237.  
  238.  if (bFilesChanged  ||  bAutoRandomiseChanged)
  239.     if (! curSysSound.IsEmpty())
  240.        SaveWavFilesList(curSysSound);
  241.  
  242.  return ok;
  243. }
  244.  
  245.  
  246. BOOL CMainDialog::LoadWavFilesList(const CString& sysSound)
  247. {
  248.  BOOL ok = TRUE;
  249.  char str[20];
  250.  int ctr;
  251.  CListBox * lb = (CListBox *)GetDlgItem(ID_FILESLIST);
  252.  CButton * but = (CButton *)GetDlgItem(ID_AUTORANDOMISE);
  253.  CString wavName;
  254.  
  255.  
  256.  FlushWavFilesList();
  257.  
  258.  
  259.  lb->ResetContent();
  260.  
  261.  int qty = GetPrivateProfileInt(sysSound, "FileCount", 0, iniFileName);
  262.  
  263.  for ( ctr  = 1;
  264.        ctr <= qty;
  265.        ctr++ )
  266.      {
  267.       wsprintf(str, "SoundFile%d", ctr);
  268.  
  269.       if (GetIniString(sysSound, str, wavName))
  270.          lb->AddString(wavName);
  271.      }
  272.  
  273.  
  274.  but->SetCheck(GetPrivateProfileInt(sysSound, "Randomize", 0, iniFileName));
  275.  
  276.  
  277.  curSysSound = sysSound;
  278.  
  279.  bFilesChanged = FALSE;
  280.  bAutoRandomiseChanged = FALSE;
  281.  
  282.  return ok;
  283. }
  284.  
  285.  
  286. BOOL CMainDialog::SaveWavFilesList(const CString & sysSound)
  287. {
  288.  BOOL ok = TRUE;
  289.  int qty = 0;
  290.  int count = 0;
  291.  CListBox * lb = (CListBox *)GetDlgItem(ID_FILESLIST);
  292.  char key[30];
  293.  char value[10];
  294.  CString filename;
  295.  CButton * but = (CButton *)GetDlgItem(ID_AUTORANDOMISE);
  296.  
  297.  qty = lb->GetCount();
  298.  
  299.  if (qty == LB_ERR)
  300.     qty = 0;
  301.  
  302.  for ( count  = 1;
  303.        count <= qty;
  304.        count++ )
  305.      {
  306.       wsprintf(key, "SoundFile%d", count);
  307.  
  308.       lb->GetText(count - 1, filename);
  309.  
  310.       WritePrivateProfileString(sysSound, key, filename, iniFileName);
  311.      }
  312.  
  313.  wsprintf(value, "%d", qty);
  314.  WritePrivateProfileString(sysSound, "FileCount", value, iniFileName);
  315.  
  316.  wsprintf(value, "%d", but->GetCheck() ? 1 : 0);
  317.  WritePrivateProfileString(sysSound, "Randomize", value, iniFileName);
  318.  
  319.  
  320.  
  321.  
  322.  bFilesChanged = FALSE;
  323.  bAutoRandomiseChanged = FALSE;
  324.  
  325.  return ok;
  326. }
  327.  
  328.  
  329. void CMainDialog::OnDestroy()
  330. {
  331.  FlushWavFilesList();
  332. }
  333.  
  334.  
  335. void CMainDialog::OnDropFiles(HDROP hDrop)
  336. {
  337.  CString sysSound;
  338.  char buffer[129];
  339.  WORD qty;
  340.  CListBox * lb = (CListBox *)GetDlgItem(ID_FILESLIST);
  341.  
  342.  
  343.  if (GetSysSound(sysSound))
  344.     {
  345.      qty = DragQueryFile(hDrop, -1, NULL, 0);
  346.  
  347.      while (qty-- > 0)
  348.            {
  349.             DragQueryFile(hDrop, qty, buffer, sizeof(buffer));
  350.  
  351.             if (buffer[0])
  352.                if (lb->AddString(buffer) != LB_ERR)
  353.                   bFilesChanged = TRUE;
  354.            }
  355.     }
  356.  
  357.  DragFinish(hDrop);
  358. }
  359.  
  360.  
  361. void CMainDialog::OnAutoRandomise()
  362. {
  363.  CButton * but = (CButton *)GetDlgItem(ID_AUTORANDOMISE);
  364.  
  365.  bAutoRandomiseChanged = TRUE;
  366. }
  367.  
  368.  
  369. BOOL CMainDialog::TryToRandomizeSysSound(CString sysSound)
  370. {
  371.  BOOL randomized = FALSE;
  372.  int files;
  373.  int randomFile;
  374.  char filename[129];
  375.  char key[10];
  376.  LPSTR strptr;
  377.  char txt[150];
  378.  
  379.  if (GetPrivateProfileInt(sysSound, "Randomize", 0, iniFileName))
  380.     if (files = GetPrivateProfileInt(sysSound, "FileCount", 0, iniFileName))
  381.        {
  382.         randomFile = ((WORD)rand() % files) + 1;
  383.        
  384.         wsprintf(key, "SoundFile%d", randomFile);
  385.         if (GetPrivateProfileString(sysSound, key, "", filename, sizeof(filename), iniFileName))
  386.            {
  387.             GetProfileString("sounds", sysSound, "", scratchBuffer, sizeof(scratchBuffer));
  388.        
  389.             strptr = scratchBuffer;
  390.             while (*strptr && *strptr != ',')
  391.                   strptr++;
  392.        
  393.             if (*strptr == ',')
  394.                {
  395.                 lstrcpy(txt, filename);
  396.                 lstrcat(txt, strptr);
  397.        
  398.                 WriteProfileString("sounds", sysSound, txt);
  399.        
  400.                 randomized = TRUE;
  401.                }
  402.            }
  403.        }
  404.  
  405.  return randomized;
  406. }
  407.  
  408.  
  409. void CMainDialog::OnRandomiseNow()
  410. {
  411.  static char buffer[512];
  412.  LPSTR p;
  413.  BOOL winIniChanged = FALSE;
  414.  
  415.  FlushWavFilesList();
  416.  
  417.  if (GetProfileString( "sounds", NULL, "", buffer, sizeof(buffer)))
  418.     {
  419.      p = buffer;
  420.  
  421.      while (*p)
  422.            {
  423.             if (TryToRandomizeSysSound(p))
  424.                winIniChanged = TRUE;
  425.  
  426.             p += lstrlen(p) + 1;
  427.            }
  428.  
  429.      if (winIniChanged)
  430.         ::SendMessage((HWND)0xFFFF, WM_WININICHANGE, 0, (LONG)(LPSTR)"sounds");
  431.     }
  432.  
  433.  
  434.  if (myApp.WantedMinimize())
  435.     {
  436.      DWORD oldtime = GetCurrentTime(),
  437.            newtime;
  438.      MSG msg;
  439.  
  440.      while (oldtime <= (newtime = GetCurrentTime()))
  441.            if (newtime > oldtime + 5000L)
  442.               break;
  443.            else
  444.               if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  445.                  if (! IsDialogMessage(&msg))
  446.                     CDialog::PreTranslateMessage(&msg);
  447.  
  448.      EndDialog(0);
  449.     }
  450. }
  451.  
  452.  
  453. void CMainDialog::OnFileSelChange()
  454. {
  455.  CListBox * lb = (CListBox *)GetDlgItem(ID_FILESLIST);
  456.  CButton * but = (CButton *)GetDlgItem(ID_PLAYSOUNDFILE);
  457.  
  458.  but->EnableWindow(lb->GetCurSel() != LB_ERR);
  459. }
  460.  
  461.  
  462. void CMainDialog::OnPlaySound()
  463. {
  464.  CListBox * lb = (CListBox *)GetDlgItem(ID_FILESLIST);
  465.  CString txt;
  466.  int curSel = lb->GetCurSel();
  467.  
  468.  if (curSel != LB_ERR)
  469.     {
  470.      lb->GetText(curSel, txt);
  471.      sndPlaySound(txt, SND_ASYNC | SND_NODEFAULT);
  472.     }
  473. }
  474.  
  475.  
  476. void CMainDialog::OnRemoveSoundFile()
  477. {
  478.  CListBox * lb = (CListBox *)GetDlgItem(ID_FILESLIST);
  479.  CString txt;
  480.  int curSel = lb->GetCurSel();
  481.  int count;
  482.  
  483.  if (curSel != LB_ERR)
  484.     {
  485.      lb->DeleteString(curSel);
  486.  
  487.      count = lb->GetCount();
  488.  
  489.      if (count != LB_ERR  &&  count > 0)
  490.         {
  491.          if (curSel >= count)
  492.             curSel = count - 1;
  493.  
  494.          lb->SetCurSel(curSel);
  495.         }
  496.  
  497.      bFilesChanged = TRUE;
  498.     }
  499. }
  500.  
  501.  
  502. void CMainDialog::OnAddSoundFile()
  503. {
  504.  CListBox * lb = (CListBox *)GetDlgItem(ID_FILESLIST);
  505.  CString txt;
  506.  int curSel = lb->GetCurSel();
  507.  OPENFILENAME o;
  508.  char buffer[129];
  509.  
  510.  lstrcpy(buffer, "*.wav");
  511.  
  512.  memset(&o, 0, sizeof(o));
  513.  
  514.  o.lStructSize  = sizeof(o);
  515.  o.hwndOwner    = GetSafeHwnd();
  516.  o.lpstrFilter  = "Sound Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0\0";
  517.  o.nFilterIndex = 1;
  518.  o.lpstrFile    = buffer;
  519.  o.nMaxFile     = sizeof(buffer);
  520.  o.lpstrTitle   = "Add Sound File";
  521.  o.Flags        = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  522.  
  523.  if (GetOpenFileName(&o))
  524.     {
  525.      if (lb->AddString(o.lpstrFile) != LB_ERR)
  526.         bFilesChanged = TRUE;
  527.     }
  528. }
  529.  
  530.  
  531. void CMainDialog::OnSysSndSelChange()
  532. {
  533.  CComboBox * cb = (CComboBox *)GetDlgItem(ID_SYSTEMSOUNDS);
  534.  
  535.  CString * s = (CString *)(soundsList.GetAt(soundsList.FindIndex(cb->GetCurSel())));
  536.  
  537.  LoadWavFilesList(*s);
  538.  
  539.  curSysSound = *s;
  540. }
  541.  
  542. void CMainDialog::OnAbout()
  543. {
  544.  MessageBox( "RandySnd is ⌐ Anthony McCarthy, 1992.\n\n"
  545.              "Feel free to use the program and/or play with the source for your "
  546.              "personal enjoyment. However, re-sale of the executable or use of "
  547.              "the source in a commercial "
  548.              "environment (that is, if you're making any money out of my efforts) "
  549.              "is not permitted without my express permission.\n"
  550.              "\n"
  551.              "This program is free and so is provided with NO WARRANTY WHATSOEVER. "
  552.              "If you're worried about it failing in any way, please delete it now.\n\n"
  553.              "However, I'll gladly accept flames regarding bugs, absent features "
  554.              "and my coding style!\n"
  555.              "\n"
  556.              "Enquiries to:\n"
  557.              "\t100012.3712@compuserve.com\n"
  558.              "\tamccarthy@cix.compulink.co.uk\n"
  559.              "\tamc@beryl.demon.co.uk\n"
  560.              "\n"
  561.              "Oh, and if you really, really like the program, feel free "
  562.              "to send a little donation!",
  563.              "About RandySnd",
  564.              MB_OK | MB_ICONASTERISK );
  565. }
  566.  
  567.  
  568.  
  569. BOOL CMainDialog::OnInitDialog()
  570. {
  571.  LPSTR p;
  572.  CComboBox * cb = (CComboBox *)GetDlgItem(ID_SYSTEMSOUNDS);
  573.  char str[150];
  574.  LPSTR strptr;
  575.  
  576.  srand((WORD)GetCurrentTime());
  577.  
  578.  rand(); // I've seen reports of MS' rand() routine starting off
  579.  rand(); // rather badly. So I call it a few times to get it going...
  580.  rand(); // (I haven't analysed it myself but this doesn't hurt, so
  581.          // what the heck...)
  582.  
  583.  
  584.  if (templateId == IDD_MAIN)
  585.     {
  586.      GetProfileString( "sounds", NULL, "", scratchBuffer, sizeof(scratchBuffer));
  587.      
  588.      p = scratchBuffer;
  589.      
  590.      while (*p)
  591.            {
  592.             GetProfileString("sounds", p, "", str, sizeof(str));
  593.      
  594.             strptr = str;
  595.             while (*strptr && *strptr != ',')
  596.                   strptr++;
  597.      
  598.             if (*strptr)
  599.                {
  600.                 cb->InsertString(-1, strptr + 1 /* skip comma */);
  601.                 soundsList.AddTail(new CString(p)); 
  602.                }
  603.      
  604.             p += lstrlen(p) + 1;
  605.            }
  606.      
  607.      cb->SetCurSel(0);
  608.      cb->SetFocus();
  609.      
  610.      DragAcceptFiles(GetSafeHwnd(), TRUE);
  611.     }
  612.  
  613.  
  614.  // Kick off the randomizing action every time the
  615.  // program runs "minimized" (but not when normal size)
  616.  
  617.  if (myApp.WantedMinimize())
  618.     PostMessage( WM_COMMAND, 
  619.                  ID_RANDOMIZENOW
  620.                );
  621.  
  622.  
  623.  return TRUE;
  624. }
  625.  
  626.  
  627.  
  628.  
  629. /* eof: randysnd.cpp */
  630.  
  631.